/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS may be copied only under the terms of the GNU General
* Public License V3, which may be found in the FastDFS source kit.
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
**/

//fc_proto.h

#ifndef _FC_PROTO_H_
#define _FC_PROTO_H_

#include "fc_types.h"

#define FC_PROTO_CMD_QUIT	10

#define FC_PROTO_CMD_POST_THREAD_T		11
#define FC_PROTO_CMD_REPLY_THREAD_T		12
#define FC_PROTO_CMD_GET_THREADS_T		13
#define FC_PROTO_CMD_GET_ELITE_THREADS_T		14
#define FC_PROTO_CMD_GET_ID_THREADS	15
#define FC_PROTO_CMD_GET_NEWEST_THREADS	16
#define FC_PROTO_CMD_GET_HOTEST_THREADS	17
#define FC_PROTO_CMD_GET_POSTS_T	18
#define FC_PROTO_CMD_SET_TOP_T	19
#define FC_PROTO_CMD_UNSET_TOP_T	20
#define FC_PROTO_CMD_SET_ELITE_T	21
#define FC_PROTO_CMD_UNSET_ELITE_T	22
#define FC_PROTO_CMD_LOCK_THREAD_T	23
#define FC_PROTO_CMD_UNLOCK_THREAD_T	24
#define FC_PROTO_CMD_DELETE_THREAD_T	25
#define FC_PROTO_CMD_UNDELETE_THREAD_T	26
#define FC_PROTO_CMD_DELETE_POST_T	27
#define FC_PROTO_CMD_UNDELETE_POST_T	28
#define FC_PROTO_CMD_SET_TYPE_T	29
#define FC_PROTO_CMD_UNSET_TYPE_T	30
#define FC_PROTO_CMD_SET_ATTACH_TYPE_T	31
#define FC_PROTO_CMD_UNSET_ATTACH_TYPE_T	32
#define FC_PROTO_CMD_SET_STATUS_T	33
#define FC_PROTO_CMD_UNSET_STATUS_T	34
#define FC_PROTO_CMD_EDIT_THREAD_T	35

#define FC_PROTO_CMD_POST_THREAD_P	36
#define FC_PROTO_CMD_REPLY_THREAD_P	37
#define FC_PROTO_CMD_GET_POSTS_P	38
#define FC_PROTO_CMD_GET_LAST_POSTS_P	39
#define FC_PROTO_CMD_DELETE_THREAD_P	40
#define FC_PROTO_CMD_UNDELETE_THREAD_P	41
#define FC_PROTO_CMD_DELETE_POST_P	42
#define FC_PROTO_CMD_UNDELETE_POST_P	43
#define FC_PROTO_CMD_SET_ATTACH_TYPE_P	44
#define FC_PROTO_CMD_UNSET_ATTACH_TYPE_P	45
#define FC_PROTO_CMD_EDIT_POST_P	46

#define FC_PROTO_CMD_HEART_BEAT  80

#define FC_PROTO_CMD_RESP        100

#define FC_PROTO_PKG_LEN_SIZE		4
#define FC_PROTO_CMD_SIZE		1

typedef int fc_pkg_size_t;

#define PACK_BODY_THREAD_RAW(pThreadRaw, p) \
	int2buff(pThreadRaw->board_id, p); \
	p += 4; \
	int2buff(pThreadRaw->thread_id, p); \
	p += 4; \
	int2buff(pThreadRaw->title_len, p); \
	p += 4; \
	if (pThreadRaw->title_len > 0) \
	{ \
		memcpy(p, pThreadRaw->title, pThreadRaw->title_len); \
		p += pThreadRaw->title_len; \
	} \
	int2buff(pThreadRaw->creator_len, p);  \
	p += 4; \
	if (pThreadRaw->creator_len > 0) \
	{ \
		memcpy(p, pThreadRaw->creator, pThreadRaw->creator_len); \
		p += pThreadRaw->creator_len; \
	} \
	int2buff(pThreadRaw->creator_nick_len, p);  \
	p += 4; \
	if (pThreadRaw->creator_nick_len > 0) \
	{ \
		memcpy(p, pThreadRaw->creator_nick, pThreadRaw->creator_nick_len); \
		p += pThreadRaw->creator_nick_len; \
	} \
	int2buff(pThreadRaw->create_ip, p);  \
	p += 4; \
	int2buff(pThreadRaw->types, p);  \
	p += 4; \
	int2buff(pThreadRaw->attach_type, p);  \
	p += 4; \
	int2buff(pThreadRaw->area_len, p);  \
	p += 4; \
	if (pThreadRaw->area_len > 0) \
	{ \
		memcpy(p, pThreadRaw->area, pThreadRaw->area_len); \
		p += pThreadRaw->area_len; \
	} \
	int2buff(pThreadRaw->post_node, p);  \
	p += 4; \
	int2buff(pThreadRaw->post_table_len, p);  \
	p += 4; \
	if (pThreadRaw->post_table_len > 0) \
	{ \
		memcpy(p, pThreadRaw->post_table, pThreadRaw->post_table_len); \
		p += pThreadRaw->post_table_len; \
	} \

#define PACK_BODY_POST_RAW(pPostRaw, p) \
	int2buff(pPostRaw->board_id, p); \
	p += 4; \
	int2buff(pPostRaw->thread_id, p); \
	p += 4; \
	int2buff(pPostRaw->post_id, p); \
	p += 4; \
	int2buff(pPostRaw->title_len, p); \
	p += 4; \
	if (pPostRaw->title_len > 0) \
	{ \
		memcpy(p, pPostRaw->title, pPostRaw->title_len); \
		p += pPostRaw->title_len; \
	} \
	int2buff(pPostRaw->creator_len, p);  \
	p += 4; \
	if (pPostRaw->creator_len > 0) \
	{ \
		memcpy(p, pPostRaw->creator, pPostRaw->creator_len); \
		p += pPostRaw->creator_len; \
	} \
	int2buff(pPostRaw->creator_nick_len, p);  \
	p += 4; \
	if (pPostRaw->creator_nick_len > 0) \
	{ \
		memcpy(p, pPostRaw->creator_nick, pPostRaw->creator_nick_len); \
		p += pPostRaw->creator_nick_len; \
	} \
	int2buff(pPostRaw->create_ip, p);  \
	p += 4; \
	int2buff(pPostRaw->attach_type, p);  \
	p += 4; \
	int2buff(pPostRaw->floor, p);  \
	p += 4; \

typedef struct
{
	char pkg_len[FC_PROTO_PKG_LEN_SIZE];  //body length
	char timestamp[FC_PROTO_PKG_LEN_SIZE]; //current time
	char cmd;
	char keep_alive;
	char status;
} ProtoHeader;

#ifdef __cplusplus
extern "C" {
#endif

int fc_recv_header(FCServerInfo *pServer, fc_pkg_size_t *in_bytes);

int fc_recv_response(FCServerInfo *pServer, \
		char **buff, const int buff_size, \
		fc_pkg_size_t *in_bytes);
int fc_quit(FCServerInfo *pServer);

/**
* connect to the server
* params:
*	pServer: server
* return: 0 success, !=0 fail, return the error code
**/
int fc_connect_server(FCServerInfo *pServer);

/**
* close connection to the server
* params:
*	pServer: server
* return:
**/
void fc_disconnect_server(FCServerInfo *pServer);

int fc_client_post_thread_t(FCServerInfo *pServer, const char keep_alive, \
	const time_t timestamp, const int prot_cmd, \
	FCThreadRaw *pThreadRaw);

int fc_client_reply_thread_t(FCServerInfo *pServer, const char keep_alive, \
	const time_t timestamp, const int prot_cmd, \
	FCPostRaw *pPostRaw);

int fc_client_heart_beat(FCServerInfo *pServer);

#ifdef __cplusplus
}
#endif

#endif

